use axum::{ routing::{delete, get, post},  Router};
use tower_http::services::{ServeDir, ServeFile};
use crate::get_path::get_path;
use tokio::net::TcpListener;
use tower_http::trace::TraceLayer;
use std::net::SocketAddr;
use tower_http::trace::DefaultMakeSpan;
use crate::web_api::web_socket::ws_handler;
use super::sisu_login_url::{get_sisu_login_url, set_sisu_code_and_state};
use super::stream_start_or_stop::{stream_start, stream_stop};
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
use tokio::signal;
use super::setting::{get_setting, set_setting, logout};
use super::console::{_get_console, _save_console};

pub async fn axum_init() {
    // 初始化日志
    tracing_subscriber::registry()
        .with(
            tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| {
                format!("{}=debug,tower_http=debug", env!("CARGO_CRATE_NAME")).into()
            }),
        )
        .with(tracing_subscriber::fmt::layer())
        .init();

    let static_path = get_path().join("static");
    if !static_path.exists() {
        std::fs::create_dir_all(static_path.clone()).unwrap();
    }

    let static_service = Router::new()
        .fallback_service(
            ServeDir::new(static_path.clone())
                .not_found_service(ServeFile::new(static_path.join("index.html")))
        );
    
    let app = Router::new()
        // .route("/ws", get(ws_handler))
        .route("/api/get_sisu_login_url", get(get_sisu_login_url))
        .route("/api/set_sisu_code_and_state", post(set_sisu_code_and_state))
        .route("/api/stream_start", get(stream_start))
        .route("/api/stream_stop", get(stream_stop))
        .route("/api/setting", get(get_setting).post(set_setting))
        .route("/api/logout", delete(logout))
        .route("/api/console", get(_get_console).post(_save_console))
        .fallback_service(static_service)
        .layer(
            TraceLayer::new_for_http()
                .make_span_with(DefaultMakeSpan::default().include_headers(true)),
        );
    
    let addr = "0.0.0.0:3200";
    println!("🚀 服务已启动：http://{}", addr);

    let listener = TcpListener::bind(addr).await.unwrap();
    tracing::debug!("listening on {}", listener.local_addr().unwrap());

    // 启动 Axum 服务，支持优雅关闭
    let server = axum::serve(
        listener,
        app.into_make_service_with_connect_info::<SocketAddr>(),
    )
    .with_graceful_shutdown(shutdown_signal());

    // 等待服务器结束
    if let Err(e) = server.await {
        eprintln!("服务器错误: {}", e);
    }
    
    println!("服务器已完全关闭");
}

// 处理关闭信号的异步函数
async fn shutdown_signal() {
    // 处理 Ctrl+C
    let ctrl_c = async {
        signal::ctrl_c()
            .await
            .expect("failed to install Ctrl+C handler");
        println!("\n接收到 Ctrl+C，正在关闭服务器...");
    };

    // Unix 系统特有的信号处理
    #[cfg(unix)]
    let terminate = async {
        signal::unix::signal(signal::unix::SignalKind::terminate())
            .expect("failed to install signal handler")
            .recv()
            .await;
        println!("接收到 SIGTERM，正在关闭服务器...");
    };

    // 非 Unix 系统，使用一个永远不会完成的任务
    #[cfg(not(unix))]
    let terminate = std::future::pending::<()>();

    // 等待任意信号
    tokio::select! {
        _ = ctrl_c => {},
        _ = terminate => {},
    }

    // 给一点时间让日志输出
    tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
}